package rule20.validatecode.processor;

import org.apache.commons.lang3.StringUtils;
import rule20.ValidateCode;
import rule20.ValidateCodeType;
import rule20.validatecode.generator.ImageValidateCodeGenerator;
import rule20.validatecode.generator.SmsValidateCodeGenerator;
import rule20.validatecode.generator.ValidateCodeGenerator;

import java.util.HashMap;
import java.util.Map;

/**
 * @author ChangLiang
 * @date 2020/3/18
 */
public abstract class AbstractValidateCodeProcessor<C extends ValidateCode> implements ValidateCodeProcessor {

    /**
     * 分层封装思想 hierarchical encapsulation
     * @return
     */
    private static Map<String, ValidateCodeGenerator> validateCodeGeneratorMap;

    static{
        validateCodeGeneratorMap = new HashMap<>(2);
        validateCodeGeneratorMap.put("smsValidateCodeGenerator", new SmsValidateCodeGenerator());
        validateCodeGeneratorMap.put("imageValidateCodeGenerator", new ImageValidateCodeGenerator());
    }

    @Override
    public void create() {
        // 生成 hierarchical encapsulation
        // generator interface
        // generate sms or image
        C validateCode = generate();
        // 保存
        save(validateCode);
        // 发送 abstract method realize by subclass
        // sms send
        // image send
        send(validateCode);
    }

    @Override
    public void validate() {
        System.out.println("do common validate");
    }

    protected abstract void send(C validateCode);

    private void save(C validateCode) {
        System.out.println("save validateCode");
    }


    private C generate(){
        String type = getValidateCodeType().toString().toLowerCase();
        String generatorName = type + ValidateCodeGenerator.class.getSimpleName();
        // 依赖查找
        ValidateCodeGenerator codeGenerator = validateCodeGeneratorMap.get(generatorName);
        return (C) codeGenerator.generate();
    }

    /**
     * 获得子类CodeProcessor可以处理的ValidateCode
     * 子类getClass().getSimpleName()值不同
     * @return
     */
    private ValidateCodeType getValidateCodeType() {
        // 两个子类 ImageCodeProcessor SmsCodeProcessor
        String type = StringUtils.substringBefore(getClass().getSimpleName(), "CodeProcessor");
        return ValidateCodeType.valueOf(type.toUpperCase());
    }
}
